#ifndef MASQUE_H
#define MASQUE_H
/**
 * \file Masque.h
 * \brief Définit un Masque
 *
 */
#include <list>
#include <GL/glut.h>
#include "../include/Image.h"
#include "../include/Pixel.h"

struct Point{
	int x,y,nbIt;
	Point(int _x,int _y,int _nbIt):x(_x),y(_y),nbIt(_nbIt){};
};

/*! \class Masque
* \brief Classe Masque binaire
*
*  La classe permet l'utilisation d'un masque binaire de la taille de l'image à inpainter. Les valeurs sont enregistré a 0 ou 255.
*/

class Masque{

public:
/*!
 *  \brief Constructeur
 *
 *  Constructeur de la classe Masque
 *
 *  \param l : largeur du masque
 *  \param h : hauteur du masque
 */
	Masque(int _l,int _h);
/*!
 *  \brief Destructeur
 *
 *  Destructeur de la classe Masque
 * 
 */
	~Masque();
/*!
 *  \brief Lit une valeur
 *
 *  Methode qui permet de lire une valeur dans le masque, 0 ou 255
 *
 *  \param x : coordonnées en x de la valeur a lire
 *  \param y : coordonnées en y de la valeur a lire
 *  \return renvoie 0 ou 255 suivant que le masque est faux ou vrai
 */
	GLubyte Lit(int _x,int _y,bool tmp=false);
/*!
 *  \brief Lit une valeur
 *
 *  Methode qui permet de lire une valeur dans le masque, false ou true
 *
 *  \param x : coordonnées en x de la valeur a lire
 *  \param y : coordonnées en y de la valeur a lire
 *  \return renvoie false ou true suivant que le masque est faux ou vrai
 */
	bool LitBool(int _x,int _y,bool tmp=false);
/*!
 *  \brief Ecrit une valeur
 *
 *  Methode qui permet d'ecrire une valeur dans le masque
 *
 *  \param x : coordonnées en x de la valeur a ecrire
 *  \param y : coordonnées en y de la valeur a ecrire
 *  \param b : couleur de la valeur a ecrire
 *  \return void
 */
	void Ecrit(int _x,int _y,GLubyte _b,bool tmp=false);
/*!
 *  \brief Dessine dans le masque
 *
 *  Methode qui permet de dessiner/effacer dans le masque en utilisant l'algo de bresenham
 *
 *  \param xa : coordonnées en x du premier point
 *  \param ya : coordonnées en y du premier point
 *  \param xb : coordonnées en x du second point
 *  \param yb : coordonnées en y du second point
 *  \param couleur : permet de dessiner/effacer en passant 255/0 comme valeur
 *  \return void
 */
	void Dessine(int _xa,int _ya,int _xb, int _yb, int _couleur);
/*!
 *  \brief Affiche le masque
 *
 *  Methode qui permet d'afficher le masque en transparence par dessus l'image
 *
 *  \return void
 */	
	void Afficher();
/*!
 *  \brief Affiche le pinceau
 *
 *  Methode qui permet d'afficher un petit carré blanc superposé a la souris pour afficher la taille du pinceau
 *  \param x : coordonées en x de la souris
 *  \param y : coordonées en y de la souris
 *  \return void
 */	
	void AffichePinceau(int x,int y);

/*!
 *  \brief Efface le masque
 *
 *  Methode qui rempli le masque avec la valeur 0
 *
 *  \return void
 */
	void Effacer();
/*!
 *  \brief Modifie la taille du pinceau
 *
 *  Methode qui permet de modifier la taille du pinceau qui remplit le masque dans la methode dessine
 *  \param t : taille du pinceau 
 *  \return void
 */
	void setTaillePinceau(int t);
/*!
 *  \brief Accesseur taille du pinceau
 *
 *  Renvoie la taille du pinceau
 *
 *  \return renvoie la taille du pinceau
 */
	int getTaillePinceau();
	
/*!
 *  \brief Construit un masque a partir d'une image et d'une couleur
 *
 *  Methode qui met a 1 (255) le masque en (i,j) si le pixel correspondant dans l'image est de la couleur voulue.
 *  \param I : image a partir de laquelle le masque est créé.
 *  \param p : Pixel ou l'on stocke la couleur voulue.
 *  \return void
 */
	void getMaskFromPicture ( Image* I, Pixel p );

/*!
 *  \brief Calcule le rectangle incluant le masque
 *
 *  :)
 *  \return void
 */	
	void getBounds ( int * _xmin, int * _xmax, int * _ymin, int * _ymax );
	
/*!
 *  \brief Empile les valeurs "vrai" du masque dans un tableau de Point 2D
 *  Empile les valeurs "vrai" du masque dans un tableau de Point 2D pour permettre un parcours des points du masque plus rapide
 *  \return void
 */	
	void empiler();
	std::list<Point> listePos;/*!<valeurs du masque empilées*/
/*!
 *  \brief Réalise une dilatation du masque
 *  Réalise une dilatation d'ordre 'ordre' de data du masque et le stock dans dataTmp
 * \param ordre : taille de dilatation
 *  \return void
 */	
	void dilatation(int ordre);
/*!
 *  \brief Réalise une erosion du masque
 *  Réalise une erosion d'ordre 'ordre' de data du masque et le stock dans dataTmp
 *  \param ordre : taille de l'erosion
 *  \return void
 */	
	void erosion(int ordre);
/*!
 *  \brief Recupere la 1ere bande de masque (Deprecated)
 *  Recupere la 1ere bande de masque en réalisant une erosion qu'on soustrait au masque total
 *  \return void
 */	
	void getBande();
/*!
 *  \brief Recupere les bandes de masque suivantes (Deprecated)
 *  Recupere les bande suivantes de masque en réalisant une dilatation puis une erosion qu'on soustrait au masque total
 *  \return void
 */	
	bool getNextBande();
/*!
 *  \brief Pondere le masque
 *  Fonction qui permet d'appliquer des valeurs au zones du masque, au bord elle est maximale, et plus on se rapproche du centre, plus la valeur tend vers 1
 *  \return void
 */	
	void Traitement();
/*!
 *  \brief Test si le masque est vide
 *  Fonction qui permet de tester si le masque est vide (pour l'érodé ultime)
 *  \return void
 */	
	bool vide();
/*!
 *  \brief Met a jour les valeurs de ponderation du masque
 *  Fonction qui met a jour les valeurs du masque, si elles sont >1, on les descend de 1
 *  \return true si il n'y a plus rien a baisser, false sinon
 */	
	bool Update();

/*!
 *  \brief Functor de lecture (Deprecated (enleve de la lisibilité au code))
 * 	\param x : coordonnée en x
 * 	\param y : coordonnée en y
 * 	\param tmp : if(!tmp) on lit dans data, dans dataTmp sinon
 *  \return le GLubyte de data/dataTmp en x,y
 */	
	GLubyte operator()(const int x, const int y,bool tmp=false);
/*!
 *  \brief Functor d'écriture (Deprecated (enleve de la lisibilité au code))
 * 	\param x : coordonnée en x
 * 	\param y : coordonnée en y
 * 	\param val : valeur du pixel a ecrire
 * 	\param tmp : if(!tmp) on ecrit dans data, dans dataTmp sinon
 *  \return void
 */	
	void operator()(const int x, const int y,const GLubyte val,bool tmp=false);
	
private:
	int	largeur; /*!<Largeur du masque*/
	int	hauteur; /*!<Hauteur du masque*/
	int taillePinceau; /*!<Taille du pinceau pour le dessin dans le masque*/
	GLubyte* data; /*!<Données du masque*/
	GLubyte* dataTmp;/*!<Données temporaire du masque (pour les opérations de morpho maths*/

};
#endif
